import 'package:flutter/foundation.dart';
import '../models/habit.dart';
import 'database_service.dart';

class HabitProvider with ChangeNotifier {
  List<Habit> _habits = [];
  bool _isLoading = false;
  String _error = '';
  
  // Getters
  List<Habit> get habits => _habits;
  bool get isLoading => _isLoading;
  String get error => _error;
  
  // Get all habits for today
  List<Habit> get todayHabits => _habits;
  
  // Get completed habits count for today
  int get completedHabitsCount => _habits.where((habit) => habit.isCompletedToday()).length;
  
  // Get total habits count
  int get totalHabitsCount => _habits.length;
  
  // Get completion percentage for today
  double get completionPercentage {
    if (_habits.isEmpty) return 0.0;
    return completedHabitsCount / totalHabitsCount;
  }
  
  // Get the current streak (use the maximum streak from all habits)
  int get currentStreak {
    if (_habits.isEmpty) return 0;
    return _habits.map((habit) => habit.getStreakCount()).reduce((max, streakCount) => 
      streakCount > max ? streakCount : max);
  }
  
  // Initialize habits from database
  Future<void> loadHabits() async {
    _isLoading = true;
    _error = '';
    notifyListeners();
    
    try {
      _habits = await DatabaseService.instance.getHabits();
      _isLoading = false;
      notifyListeners();
    } catch (e) {
      _isLoading = false;
      _error = 'Failed to load habits: $e';
      notifyListeners();
    }
  }
  
  // Add a new habit
  Future<void> addHabit(Habit habit) async {
    try {
      await DatabaseService.instance.addHabit(habit);
      _habits.add(habit);
      notifyListeners();
    } catch (e) {
      _error = 'Failed to add habit: $e';
      notifyListeners();
    }
  }
  
  // Update a habit
  Future<void> updateHabit(Habit updatedHabit) async {
    try {
      await DatabaseService.instance.updateHabit(updatedHabit);
      
      final index = _habits.indexWhere((h) => h.id == updatedHabit.id);
      if (index != -1) {
        _habits[index] = updatedHabit;
        notifyListeners();
      }
    } catch (e) {
      _error = 'Failed to update habit: $e';
      notifyListeners();
    }
  }
  
  // Delete a habit
  Future<void> deleteHabit(String id) async {
    try {
      await DatabaseService.instance.deleteHabit(id);
      
      _habits.removeWhere((h) => h.id == id);
      notifyListeners();
    } catch (e) {
      _error = 'Failed to delete habit: $e';
      notifyListeners();
    }
  }
  
  // Toggle habit completion for today
  Future<void> toggleHabitCompletion(Habit habit) async {
    try {
      final updatedHabit = await DatabaseService.instance.toggleHabitCompletion(habit);
      
      final index = _habits.indexWhere((h) => h.id == habit.id);
      if (index != -1) {
        _habits[index] = updatedHabit;
        notifyListeners();
      }
    } catch (e) {
      _error = 'Failed to toggle habit completion: $e';
      notifyListeners();
    }
  }
  
  // Get all completed dates for a specific habit
  List<DateTime> getCompletedDatesForHabit(String habitId) {
    final habit = _habits.firstWhere((h) => h.id == habitId, orElse: () => Habit(name: ''));
    return habit.id.isNotEmpty ? habit.completedDates : [];
  }
  
  // Get completion count for each day of the week
  Map<int, int> getWeeklyCompletionData() {
    final now = DateTime.now();
    final today = DateTime(now.year, now.month, now.day);
    
    // Map days of week (1 = Monday, 7 = Sunday) to completion counts
    final Map<int, int> weeklyData = {};
    
    // Initialize all days with 0 completed
    for (int i = 1; i <= 7; i++) {
      weeklyData[i] = 0;
    }
    
    // For each habit, count completions in the last 7 days
    for (final habit in _habits) {
      for (final date in habit.completedDates) {
        final difference = today.difference(date).inDays;
        
        // Only include dates within the last 7 days
        if (difference >= 0 && difference < 7) {
          // Get day of week (1-7)
          final dayOfWeek = date.weekday;
          weeklyData[dayOfWeek] = (weeklyData[dayOfWeek] ?? 0) + 1;
        }
      }
    }
    
    return weeklyData;
  }
}
